<?php
// +----------------------------------------------------------------------
// | B5Yii2CMF V3.0 [快捷通用基础管理开发平台]
// +----------------------------------------------------------------------
// | Author: 冰舞 <357145480@qq.com>
// +----------------------------------------------------------------------
declare (strict_types=1);

namespace api\modules\v1;

use api\utils\libs\BaseController;
use api\utils\libs\FilterLogin;
use common\extend\exception\ErrorCode;
use common\extend\exception\B5HttpException;
use common\models\system\Admin;
use common\models\system\AppToken;

/**
 * 接口公共基类
 * Class ApiController
 * @package api\modules\v1
 */
class ApiController extends BaseController
{
    protected int $userId = 0;
    protected ?Admin $user = null;
    protected ?AppToken $appToken = null;
    protected bool $checkToken = false; //是否检测token，当确定一个控制器里的方法不需要检测token，可设为false，节省一次token查询

    protected bool $tokenFailBack = false; // token验证失败是否立即返回错误

    /**
     * 方法前执行操作
     * @param $action
     * @return bool
     * @throws B5HttpException
     */
    public function beforeAction($action): bool
    {
        if (!parent::beforeAction($action)) {
            return false;
        }
        if ($this->checkToken) $this->checkLoginToken();
        return true;
    }

    /**
     * 获取用户ID，用于$checkToken = false的控制中的某个方法
     * @param bool $failBack
     * @return int
     * @throws B5HttpException
     */
    public function getUserId($failBack = false): int
    {
        if (!$this->checkToken) $this->checkLoginToken();
        if ($this->userId < 1 && $failBack) {
            throw new B5HttpException(400,'登录会话失效，请重新登录',ErrorCode::API_TOKEN_ERROR);
        }
        return $this->userId;
    }

    /**
     * 获取登录用户信息
     * @param bool $checkInfo 用户信息错误直接返回响应
     * @param bool $failBack
     * @return Admin|null
     * @throws B5HttpException
     */
    public function getUser($checkInfo = true,$failBack = true): ?Admin
    {
        $userId = $this->getUserId($failBack);
        if ($userId && !$this->user) {
            $this->user = Admin::findOne($userId);
        }
        if (!$this->user) {
            if ($failBack) {
                throw new B5HttpException(400,'账号错误，请重新登录',ErrorCode::API_TOKEN_ERROR);
            }
            return null;
        }
        if ($checkInfo) {
            if ($this->user->status !=1) {
                throw new B5HttpException(400,'账号已禁用，请重新登录',ErrorCode::API_TOKEN_ERROR);
            }
        }
        return $this->user;
    }

    /**
     * 验证token
     * @throws B5HttpException
     */
    private function checkLoginToken() {
        if (!$this->appToken) {
            $checkLogin = new FilterLogin();
            $checkLogin->type = 'user';
            $checkLogin->key = 'authorization';
            $checkLogin->plat = trim($this->request->post('_plat_', 'app'));
            $checkLogin->failBack = $this->tokenFailBack;
            $this->appToken = $checkLogin->checkLoginToken();
        }

        $this->userId = $this->appToken ? intval($this->appToken->user_id) : 0;
    }


    /**
     * 返回登录错误
     * @return array
     */
    public function loginError(): array
    {
        return $this->error('未登录或登录失效',ErrorCode::API_TOKEN_ERROR);
    }

    /**
     * 返回用户信息错误
     * @return array
     */
    public function userError(): array
    {
        return $this->error('账号不存在或已禁用',ErrorCode::API_TOKEN_ERROR);
    }
}